/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "initializations.h"
#include <string.h>
#include <time.h>
#include <sys/stat.h>

int settings_init(int argn,char *argv[],struct configuration_struct *settings,int sensitivity[]) {
/* that function is responsible for filling the settings structure */
/* with default values and command line arguments */
/* returns EXIT_FAILURE to terminates the program or EXIT_SUCCESS */
	char *str_extract;
	int i,j,end_loop;
	int sensitivity_default;
	int option_found;

	/* setting default values */
	settings->daemon=DAEMON;
	settings->uid=0;
	if(settings->daemon==EXIT_SUCCESS) {
		settings->syslog=EXIT_SUCCESS;
		syslog_flag=EXIT_SUCCESS;
	} else {
		settings->syslog=EXIT_FAILURE;
		syslog_flag=EXIT_FAILURE;
	}
	sensitivity_default=SENSITIVITY_GM45_CO60;
	for(j=0;j<SERIAL_PORTS_MAX;j++) sensitivity[j]=0;
	settings->generic_location[0]='\0';
	strncat(settings->generic_location,SERIAL_LOCATION,FILE_NAME_LENGTH);
	settings->is_serial=EXIT_SUCCESS;
	settings->num_probes=SERIAL_PORTS_NUMBER;
	settings->probe_index_start=SERIAL_PORTS_START;
	settings->file_descriptor_max=0;
	settings->activity_data_write_sampling=ACTIVITY_DATA_WRITE_SAMPLING;
	settings->pulse_data_write_sampling=PULSE_DATA_WRITE_SAMPLING;
	settings->pulse_mode=PULSE_MODE;
	settings->pulse_particule_sub_sampling=PULSE_PARTICULE_SUB_SAMPLING;
	settings->pulse_mode_particules_sampling_count=0;
	settings->pulse_mode_particules_sampling_write=1e3*(int)PULSE_DATA_WRITE_SAMPLING/(int)PULSE_PARTICULE_SUB_SAMPLING;
	settings->file_log=FILE_LOG;
	strncpy(settings->log_file_path,PROBE_LOG_FILE_PATH,FILE_NAME_LENGTH);
	#ifdef SQL_LIBS
	settings->sql_log=EXIT_FAILURE;
	#endif
	
	#ifdef SQL_LIBS
	/* strings assignment */
	strncpy(settings->sql_host,SQL_HOST,SQL_PARAMETERS_STRINGS);
	settings->sql_port=SQL_PORT;
	strncpy(settings->sql_database,SQL_DATABASE,SQL_PARAMETERS_STRINGS);
	strncpy(settings->sql_table,SQL_TABLE,SQL_PARAMETERS_STRINGS);
	strncpy(settings->sql_user,SQL_USER,SQL_PARAMETERS_STRINGS);
	strncpy(settings->sql_password,SQL_PASSWORD,SQL_PARAMETERS_STRINGS);
	#endif
	
	/* reading command line */
	switch(argn){
		case 2:{
			if((strcmp(argv[1],"-h")==0) || (strcmp(argv[1],"--help")==0) || (strcmp(argv[1],"-help")==0)){
				printf(_("%s %s (%s for %s, %s)\n"),GM4LIN_NAME,GM4LIN_VERSION,GM4LIN_AUTHOR,GM4LIN_COMPANY,GM4LIN_DATE);
				#ifdef DEBUG
					printf("DEBUG mode\n");
				#endif
				printf(_("recording of serial ports GM-10 and GM-45 Radiation Detectors\n"));
				printf(_("Options:\n"));
				printf(_("\t--daemon: run as a daemon (process detached from the shell) (default=%d)\n"),settings->daemon);
				printf(_("\t--uid: run under given uid (default=current uid)\n"));
				printf(_("\t--syslog: log errors using syslog (default=ON if running as daemon)\n"));
				printf(_("\t-d, --device [device root]: specify a device class (default=%s)\n"),settings->generic_location);
				printf(_("\t--dummy: device(s) won't be initialized as serial ports (for testing purpose with pipes)\n"));
				printf(_("\t-n, --number [number]: select the number of probes (default=%d)\n"),settings->num_probes);
				printf(_("\t-s, --start [index probe start]: starting number for the probes (default=%d)\n"),settings->probe_index_start);
				printf(_("\t-p, --pulse: radiation pulse recording mode (default=no)\n"));
				printf(_("\t--sensitivity=[nn,nn,nn]: comma delimited list of sensitivity keywords (like \"GM45_CO60\", ...)\n"));
				printf(_("\t--default-sensitivity=[keyword]: default sensitivity keywords (default=GM45_CO60)\n"));
				printf(_("\t--list-sensitivities: gives the list of available sensitivities keywords\n"));
				printf(_("\t--no-file-log: don't log data to a file (default=log)\n"));
				printf(_("\t--log-path: path to the data log files (default=%s)\n"),settings->log_file_path);
				#ifdef SQL_LIBS
				printf(_("\t--mysql [user]@[host]:[database]:[table] log data into a MySQL database (default=%s@%s:%s:%s)\n"),settings->sql_user,settings->sql_host,settings->sql_database,settings->sql_table);
				printf(_("\t--port [port]: port used to connect to MySQL database (default=%d - MySQL default=0)\n"),settings->sql_port);
				printf(_("\t--passwd [password]: password for the MySQL database (default=%s)\n"),settings->sql_password);
				#endif
				printf(_("\t-h, --help: shows this help screen\n"));
				printf(_("\t--license: shows your rights and obligation when using this software. Please read it!\n"));
				printf(_("CRTL-C when the software is running stops recording activity and exits\n"));
				printf("------------------\n");
				printf("%s\n",GM4LIN_AUTHOR_EMAIL);
				return EXIT_FAILURE;
			}
		}
	}
	end_loop=argn-1;
	/* command line arguments scan */
	for(i=1;i<=(end_loop);i++){
		option_found=0;
		if((strcasecmp(argv[i],"--license")==0)) {
			option_found=1;
			printf(_("This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\n"));
			printf(_("This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License in file \"COPYING\" for more details, or write to\n"));
			printf(_("\tFree Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA\nto obtain a copy of the license.\n"));
			return EXIT_FAILURE;
		}
		if((strcasecmp(argv[i],"-d")==0) || (strcasecmp(argv[i],"--device")==0)) {
			option_found=1;
			/* selecting a device */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for device location!\n"));
				return EXIT_FAILURE;
			}
			sscanf(argv[i],"%s",settings->generic_location);
			continue;
		}
		if(strcasecmp(argv[i],"--dummy")==0) {
			option_found=1;
			/* dummy probes -> no serial initializations */
			settings->is_serial=EXIT_FAILURE;
			continue;
		}
		if(strcasecmp(argv[i],"--daemon")==0) {
			option_found=1;
			settings->daemon=EXIT_SUCCESS;
			settings->syslog=EXIT_SUCCESS;
			syslog_flag=EXIT_SUCCESS;
			continue;
		}
		if(strcasecmp(argv[i],"--uid")==0) {
			option_found=1;
			/* reading the requested uid */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for uid selection!\n"));
				return EXIT_FAILURE;
			}
			sscanf(argv[i],"%d",&settings->uid);
			
			continue;
		}
		if(strcasecmp(argv[i],"--syslog")==0) {
			option_found=1;
			settings->syslog=EXIT_SUCCESS;
			syslog_flag=EXIT_SUCCESS;
			continue;
		}
		if((strcasecmp(argv[i],"-n")==0) || (strcasecmp(argv[i],"--number")==0)) {
			option_found=1;
			/* selecting the number of probes */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for number of devices!\n"));
				return EXIT_FAILURE;
			}
			sscanf(argv[i],"%d",&settings->num_probes);
			if (settings->num_probes>SERIAL_PORTS_MAX) {
				error_log(_("settings_init: too many probes required\n"));
				return EXIT_FAILURE;	
			}
			continue;
		}
		if((strcasecmp(argv[i],"-s")==0) || (strcasecmp(argv[i],"--start")==0)){
			option_found=1;
			/* selecting the index of the first probe */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for first device number!\n"));
				return EXIT_FAILURE;
			}
			sscanf(argv[i],"%d",&settings->probe_index_start);
			continue;
		}
		if((strcasecmp(argv[i],"-p")==0) || (strcasecmp(argv[i],"--pulse")==0)){
			option_found=1;
			/* switching to pulse recording mode */
			settings->pulse_mode=EXIT_SUCCESS;
			continue;
		}
		if(strncasecmp(argv[i],"--sensitivity",strlen("--sensitivity"))==0){
			option_found=1;
			/* reading the list of index for gm10 detectors */
			j=0;
			str_extract=(char *)strtok(argv[i],"=");
			str_extract=(char *)strtok(NULL,"=");
			str_extract=(char *)strtok(str_extract,",");
			while((str_extract!=NULL) && (j<SERIAL_PORTS_MAX)) {
				if(strcasecmp(str_extract,"GM45_CO60")==0) sensitivity[j]=SENSITIVITY_GM45_CO60;
				if(strcasecmp(str_extract,"GM10_CO60")==0) sensitivity[j]=SENSITIVITY_GM10_CO60;
				if(strcasecmp(str_extract,"GM10_CS137")==0) sensitivity[j]=SENSITIVITY_GM10_CS137;
				str_extract=(char *)strtok(NULL,",");
				j++;
			}
			if(j>=SERIAL_PORTS_MAX) error_log(_("initialization.c: too many sensitivities given, ignoring them\n"));
			continue;
		}
		if(strncasecmp(argv[i],"--default-sensitivity",strlen("--default-sensitivity"))==0){
			option_found=1;
			/* reading and writing default sensitivity in the sensitivity table */
			str_extract=(char *)strtok(argv[i],"=");
			str_extract=(char *)strtok(NULL,"=");
			if(str_extract!=NULL) {
				if(strcasecmp(str_extract,"GM45_CO60")==0) sensitivity_default=SENSITIVITY_GM45_CO60;
				if(strcasecmp(str_extract,"GM10_CO60")==0) sensitivity_default=SENSITIVITY_GM10_CO60;
				if(strcasecmp(str_extract,"GM10_CS137")==0) sensitivity[j++]=SENSITIVITY_GM10_CS137;
			} else {
				error_log(_("settings_init: wrong syntax for default sensitivity selection\n"));
				return EXIT_FAILURE;
			}
			continue;
		}
		if(strcasecmp(argv[i],"--list-sensitivities")==0){
			option_found=1;
			/* giving the list of available sensitivities */
			printf(_("Available sensitivity keywords and their values (in cps/mR/h):\n"));
			printf(_("keyword -> value\n"));
			printf("GM45_CO60 -> %d\n",SENSITIVITY_GM45_CO60);
			printf("GM10_CO60 -> %d\n",SENSITIVITY_GM10_CO60);
			printf("GM10_CS137 -> %d\n",SENSITIVITY_GM10_CS137);
			return EXIT_FAILURE;
		}
		if(strcasecmp(argv[i],"--no-file-log")==0){
			option_found=1;
			/* switching to pulse recording mode */
			settings->file_log=EXIT_FAILURE;
			continue;
		}
		if(strcasecmp(argv[i],"--log-path")==0){
			option_found=1;
			/* path to the data log files */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for data log path!\n"));
				return EXIT_FAILURE;
			}
			strncpy(settings->log_file_path,argv[i],FILE_NAME_LENGTH);
			continue;
		}
		#ifdef SQL_LIBS
		if((strcasecmp(argv[i],"--mysql")==0)){
			option_found=1;
			/* switching to MySQL recording mode */
			settings->sql_log=EXIT_SUCCESS;
			if(++i<=end_loop) {
				/* look if the next argument goes with --mysql or is another option */
				if(argv[i][1]=='-') {
					i--;
					continue;
				}
				/* now we can read the parameters of the sql connection */
				str_extract=(char *)strtok(argv[i],"@");
				if(str_extract!=NULL) strncpy(settings->sql_user,str_extract,SQL_PARAMETERS_STRINGS);
				str_extract=(char *)strtok(NULL,":");
				if(str_extract!=NULL) strncpy(settings->sql_host,str_extract,SQL_PARAMETERS_STRINGS);
				str_extract=(char *)strtok(NULL,":");
				if(str_extract!=NULL) strncpy(settings->sql_database,str_extract,SQL_PARAMETERS_STRINGS);
				str_extract=(char *)strtok(NULL,":");
				if(str_extract!=NULL) strncpy(settings->sql_table,str_extract,SQL_PARAMETERS_STRINGS);
			}
			continue;
		}
		if((strcasecmp(argv[i],"--port")==0)){
			option_found=1;
			/* port for MySQL recording mode */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for port selection!\n"));
				return EXIT_FAILURE;
			}
			sscanf(argv[i],"%d",&settings->sql_port);
			continue;
		}
		if((strcasecmp(argv[i],"--passwd")==0)){
			option_found=1;
			/* password for MySQL recording mode */
			if(++i>end_loop) {
				error_log(_("settings_init: not enought parameters for mysql password!\n"));
				return EXIT_FAILURE;
			}
			sscanf(argv[i],"%s",settings->sql_password);
			continue;
		}
		#endif
		if(option_found==0) {
			fprintf(stderr,_("Error: %s (%s) doesn't know option \"%s\"\n"),GM4LIN_NAME,GM4LIN_VERSION,argv[i]);
			if(syslog_flag==EXIT_SUCCESS) syslog(LOG_ERR,_("Error: %s (%s) doesn't know option \"%s\"\n"),GM4LIN_NAME,GM4LIN_VERSION,argv[i]);
			return EXIT_FAILURE;
		}
		
	}
	/* replacing in the table the default sensitivity by its value */
	for(j=0;j<SERIAL_PORTS_MAX;j++) {
		if(sensitivity[j]==0) sensitivity[j]=sensitivity_default;
	}
	
	return EXIT_SUCCESS;

}

int probe_sensitivity_init(struct probe_descriptor *probe,struct configuration_struct *settings,int sensitivity) {
/* Do the sensitivity initialization of a probe */
/* return EXIT_SUCCESS or EXIT_FAILURE */

	probe->sensitivity=sensitivity;
	/* conversion factor from signal to R/h */
	if (settings->pulse_mode==EXIT_SUCCESS) {
		probe->conv2rh=1.0/(bicron_signal2Rh*probe->sensitivity);
		probe->conv2display=1.0;
	} else {
		probe->conv2rh=1.0/(events2Rh*probe->sensitivity);
		probe->conv2display=events2cpm;
	}
	
	return EXIT_SUCCESS;
}

int probe_units_init(struct probe_descriptor *probe,struct configuration_struct *settings) {
/* Do the initialization of the units a probe */
/* return EXIT_SUCCESS or EXIT_FAILURE */
/* units used for display and real science */
	int n;

	if (settings->pulse_mode==EXIT_SUCCESS) {
		n=snprintf(probe->display_units,SHORT_STRING,"raw");
		if (n <= -1 || n >= (int)(SHORT_STRING*sizeof(char))) {
			error_log(_("probe_units_init: display_unit string building failure\n"));
			return EXIT_FAILURE;
		}
		n=snprintf(probe->si_units,SHORT_STRING,"R/h");
		if (n <= -1 || n >= (int)(SHORT_STRING*sizeof(char))) {
			error_log(_("probe_units_init: si_unit string building failure\n"));
			return EXIT_FAILURE;
		}
	} else {
		n=snprintf(probe->display_units,SHORT_STRING,"cpm");
		if (n <= -1 || n >= (int)(SHORT_STRING*sizeof(char))) {
			error_log(_("probe_units_init: display_unit string building failure\n"));
			return EXIT_FAILURE;
		}
		n=snprintf(probe->si_units,SHORT_STRING,"R/h");
		if (n <= -1 || n >= (int)(SHORT_STRING*sizeof(char))) {
			error_log(_("probe_units_init: si_unit string building failure\n"));
			return EXIT_FAILURE;
		}
	}
	
	return EXIT_SUCCESS;
}

int probe_file_log_init(struct probe_descriptor *probe,struct configuration_struct *settings) {
/* Open the log file for a probe; */
/* write its header. */
/* return EXIT_SUCCESS or EXIT_FAILURE */
	int n;
	char log_file_name[FILE_NAME_LENGTH];		/* name of the log file */
	struct tm *local_time;				/* local time structure */
	char log_date[20];				/* string containing the ISO formated time, this is 20 char long */
	time_t timing;					/* time in seconds since EPOC */

	
	/* building the file name of the probe log file */
	log_file_name[0]='\0';
	if(time(&timing) == ((time_t)-1)) {
		error_log(_("probe_file_log_init: Time reading failure\n"));
		return EXIT_FAILURE;
	}
	if((local_time=(struct tm*)localtime(&timing)) != NULL) { /* cast done because gcc was complaining. Why??? */
		strftime(log_date,(size_t)20,"%m%d%Y",(struct tm*)localtime(&timing));
	} else {
		error_log(_("probe_file_log_init: Time conversion failure"));
		return EXIT_FAILURE;
	}
	n=snprintf(log_file_name,(size_t)(FILE_NAME_LENGTH*sizeof(char)),"%s%d_%s.%s",PROBE_LOG_FILE,probe->index,log_date,PROBE_LOG_EXTENSION);
	if(n <= -1 || n >= ((int)(FILE_NAME_LENGTH*sizeof(char)))) {
		error_log(_("probe_file_log_init: Log file name too long\n"));
		return EXIT_FAILURE;
	}
	/* opening the probe log file */
	if((probe->log_file=fopen(log_file_name,"wt")) == NULL){
		error_log(_("probe_file_log_init: Log file can not be opened"));
		return EXIT_FAILURE;
	}
	#ifdef DEBUG
		printf("\tSuccessfully opened file \"%s\" for logging of probe #%d\n",log_file_name,probe->index);
	#endif
	/* header for the probe log file */
	fprintf(probe->log_file,"#%s %s (%s) - %s\n",GM4LIN_NAME,GM4LIN_VERSION,GM4LIN_DATE,GM4LIN_COMPANY);
	fprintf(probe->log_file,_("#Radiation activity record for %s%d\n"),settings->generic_location,probe->number);
	fprintf(probe->log_file,_("#Probe number %d sensitivity factor=%d\n"),probe->index,probe->sensitivity);
	fprintf(probe->log_file,"#Date_Time %s %s\n",probe->display_units,probe->si_units);
	
	return EXIT_SUCCESS;
}

int probes_init(struct probe_descriptor probe[], struct configuration_struct *settings,int sensitivity[]) {
/* initialization of the probes */
/* return EXIT_SUCCESS or EXIT_FAILURE */
	int probe_index;		/* index in order to scan the table of the probes */
	
	for(probe_index=0;probe_index<settings->num_probes;probe_index++) {
		/* PHYSICAL number of the probe we are talking about */
		probe[probe_index].number=probe_index+settings->probe_index_start;
		/* LOGICAL number of the probe we are talking about */
		probe[probe_index].index=probe_index+1;
		/* initializing sensitivity and units */
		probe_sensitivity_init(&probe[probe_index],settings,sensitivity[probe_index]);
		if(probe_units_init(&probe[probe_index],settings)==EXIT_FAILURE) {
			fprintf(stderr,_("probes_init: Can't set up probe #%d units. Displayed units will be wrong\n"),probe[probe_index].index);
			if(syslog_flag==EXIT_SUCCESS) syslog(LOG_ERR,_("probes_init: Can't set up probe #%d units. Displayed units will be wrong\n"),probe[probe_index].index);
		}
		/* giving some information about what is going on */
		printf(_("\tprobe #%d sensitivity=%d, SI units=%s\n"),probe[probe_index].index,probe[probe_index].sensitivity,probe[probe_index].si_units);
		/* Log file */
		probe[probe_index].log_file=NULL;
		if(settings->file_log==EXIT_SUCCESS) {
			if(probe_file_log_init(&probe[probe_index],settings)==EXIT_FAILURE) {
				fprintf(stderr,_("probes_init: Can't set up log file for probe #%d. File logging disabled for this probe\n"),probe[probe_index].index);
				if(syslog_flag==EXIT_SUCCESS) syslog(LOG_ERR,_("probes_init: Can't set up log file for probe #%d. File logging disabled for this probe\n"),probe[probe_index].index);
				probe[probe_index].log_file=NULL;
			}
		}
		
		/* initializing and run the probes */
		if((start_probe(&probe[probe_index],settings)) == EXIT_FAILURE) {
			error_log(_("probe_init: probe can not be started"));
			/* closing the log file */
			if ((settings->file_log==EXIT_SUCCESS) && (probe[probe_index].log_file!=NULL)) {
				if ((fclose(probe[probe_index].log_file)) != EXIT_SUCCESS){
					error_log(_("probe_init: Log file can not be closed"));
				}
			}
			return EXIT_FAILURE;
		}
		if((probe[probe_index].file_descriptor) > (settings->file_descriptor_max)) settings->file_descriptor_max=probe[probe_index].file_descriptor;
	}
	return EXIT_SUCCESS;
}

#ifdef SQL_LIBS
int sql_init(struct configuration_struct *settings) {
	char stmt_str[128];
        snprintf(stmt_str,sizeof(stmt_str),"INSERT into %s (device, dose, data, dataunits) values (?,?,?,?)", settings->sql_table);
/* initialization of the sql database connection */
/* return EXIT_SUCCESS or EXIT_FAILURE */
	if(mysql_init(&settings->mysql)==NULL) {
		error_log(_("sql_init: Failed to initialize MySQL connection\n"));
		return EXIT_FAILURE;
	}
	if (!mysql_real_connect(&settings->mysql,settings->sql_host,settings->sql_user,settings->sql_password,settings->sql_database,settings->sql_port,NULL,0)) {
		fprintf(stderr,_("sql_init: Failed to connect to database: Error: %s\n"), mysql_error(&settings->mysql));
		if(syslog_flag==EXIT_SUCCESS) syslog(LOG_ERR,_("sql_init: Failed to connect to database: Error: %s\n"), mysql_error(&settings->mysql));
		return EXIT_FAILURE;
	}
	if (mysql_select_db(&settings->mysql,settings->sql_database)) {
		fprintf(stderr,_("sql_init: Couldn't select database %s!\n%s\n"),settings->sql_database, mysql_error(&settings->mysql));
		if(syslog_flag==EXIT_SUCCESS) syslog(LOG_ERR,_("sql_init: Couldn't select database %s!\n%s\n"),settings->sql_database, mysql_error(&settings->mysql));
		return EXIT_FAILURE;
	}
        settings->mysql_stmt = mysql_stmt_init(&settings->mysql);
        if (settings->mysql_stmt == NULL) {
		fprintf(stderr,_("sql_init: Couldn't initialize statement %s!\n%s\n"),settings->sql_database, mysql_error(&settings->mysql));
		if(syslog_flag==EXIT_SUCCESS) syslog(LOG_ERR,_("sql_init: Couldn't initialize statement %s!\n%s\n"),settings->sql_database, mysql_error(&settings->mysql));
		return EXIT_FAILURE;
        }
	if (mysql_stmt_prepare (settings->mysql_stmt, stmt_str, strlen (stmt_str)) != 0) {
		fprintf(stderr,_("sql_init: Couldn't prepare statement %s: %s!\n%s\n"), stmt_str, settings->sql_database, mysql_error(&settings->mysql));
		return EXIT_FAILURE;
	}

        memset ((void *) settings->param, 0, sizeof (settings->param)); /* zero the structures */
        /* set up device */
        settings->param[0].buffer_type = MYSQL_TYPE_LONG;
        settings->param[0].is_unsigned = 0;
        settings->param[0].is_null = 0;

        /* set up dose */
        settings->param[1].buffer_type = MYSQL_TYPE_STRING;
        settings->param[1].buffer_length = 16;
        settings->param[1].is_null = 0; /* is_unsigned, buffer_length, length need not be set */

        /* set up data */
        settings->param[2].buffer_type = MYSQL_TYPE_DOUBLE;
        settings->param[2].is_null = 0; /* is_unsigned, buffer_length, length need not be set */

        /* set up datatype */
        settings->param[3].buffer_type = MYSQL_TYPE_STRING;
        settings->param[3].buffer_length = 4;
        settings->param[3].is_null = 0;

        if (mysql_stmt_bind_param (settings->mysql_stmt, settings->param) != 0)
        {
                fprintf(stderr,_("sql_init: Couldn't bind parameters for INSERT"));
                return EXIT_FAILURE;
        }

	return EXIT_SUCCESS;
}
#endif

static void sig_alrm(int sig) {
/* function called when a SIGALRM signal is catched */
	flag_alrm=1;
	#ifdef BUGGY_SIGACTION
		signal(SIGALRM,(void *)sig_alrm);
	#endif
	#ifdef DEBUG
		printf(".");
	#endif
}

static void sig_stop(int sig) {
/* function called when a SIGINT signal is catched */
	flag_stop=1;
	printf(_("************\nProgram stopping...\n"));
}

int stop_catch_init(void) {
/* this is the initialization of signal catching for the STOP and TERM signals */
/* we want to catch the signal SIGINT to stop the program in a clean way */
/* return EXIT_SUCCES or EXIT_FAILURE */
	struct sigaction stop_act;			/* for signal catching (for the end of recording) */
	
    	stop_act.sa_handler=(void *)sig_stop;
    	/* We don't want to block any other signals */
    	sigemptyset(&stop_act.sa_mask);
	stop_act.sa_flags=0;
	if (sigaction(SIGINT,&stop_act,NULL) != EXIT_SUCCESS) {
		error_log(_("stop_catch_init: signal catching failed for SIGINT"));
		return EXIT_FAILURE;
	}
	if (sigaction(SIGTERM,&stop_act,NULL) != EXIT_SUCCESS) {
	/* catching the term signal is necessary for a clean stop when running as a daemon: people */
	/* would stop it with a "kill" that would send SIGTERM instead of SIGINT in interractive session */
		error_log(_("stop_catch_init: signal catching failed for SIGTERM"));
		return EXIT_FAILURE;
	}
	
	return EXIT_SUCCESS;
}

int timer_init(long write_timer_duration, long short_timer_duration) {
/* this is the initialization of signal catching and timer */
/* first argument is the timer duration in seconds, the second one is in ms */
/* return EXIT_SUCCES or EXIT_FAILURE */
	struct itimerval timer_parameters;		/* parameters for the timer, in order to calculate cpm, dose... */
	struct sigaction timer_act;			/* for signal catching (for the timer) */
	
	/* we want to catch the signal SIGALRM in order to use it as a timer */
    	timer_act.sa_handler=(void *)sig_alrm;
    	/* We don't want to block any other signals */
    	sigemptyset(&timer_act.sa_mask);
	timer_act.sa_flags=0;
	if (sigaction(SIGALRM,&timer_act,NULL) != EXIT_SUCCESS) {
		error_log(_("timer_init: signal catching failed for SIGALRM"));
		return EXIT_FAILURE;
	}
	
	/* setting up a timer, which is going to send SIGALRM every average_length seconds */
	timer_parameters.it_value.tv_sec=write_timer_duration;
	timer_parameters.it_value.tv_usec=short_timer_duration;
	timer_parameters.it_interval.tv_sec=write_timer_duration;
	timer_parameters.it_interval.tv_usec=short_timer_duration;
	if((setitimer (ITIMER_REAL,&timer_parameters,NULL)) != EXIT_SUCCESS) {
		error_log(_("timer_init: timer setup failed"));
		return EXIT_FAILURE;
	}
	
	return EXIT_SUCCESS;
}

int timer_sync(void) {
/* wait until the number of seconds is '00' */
/* return EXIT_SUCCES or EXIT_FAILURE */
	time_t timing;				/* time in seconds since EPOC */
	
	printf(_("\tWaiting for seconds to be \"00\"\n"));
	do {
		if(time(&timing) == ((time_t)-1)) {
			error_log(_("timer_sync: Time reading failure\n"));
			return EXIT_FAILURE;
		}
	} while(((int)timing % 60) != 0);
	
	return EXIT_SUCCESS;
}

int sequencer_init(struct configuration_struct settings) {
/* starting signal catching and timer */
/* return EXIT_SUCCESS or EXIT_FAILURE */

	if(stop_catch_init() == EXIT_FAILURE) {
		error_log(_("sequencer_init: SIGINT catching initialization failure"));
		return EXIT_FAILURE;
	}
	//timer_sync();
	if(settings.pulse_mode==EXIT_FAILURE) {
		if(timer_init(settings.activity_data_write_sampling,0) == EXIT_FAILURE) {
			error_log(_("sequencer_init: Timer initialization failure"));
			return EXIT_FAILURE;
		}
	} else {
		if(timer_init(0,settings.pulse_particule_sub_sampling*1e3) == EXIT_FAILURE) {
			error_log(_("sequencer_init: Timer initialization failure"));
			return EXIT_FAILURE;
		}
		settings.pulse_mode_particules_sampling_write=1e3*settings.pulse_data_write_sampling/settings.pulse_particule_sub_sampling;
	}
	return EXIT_SUCCESS;
}

void daemonize (void) {
/* running as a daemon */
/* it doesn't return anything */
	pid_t pid;
	
	pid = fork();
	if (pid) {
		/* parent -- just exit */
		#ifdef DEBUG
			printf(_("Parent process #1 exiting\n"));
		#endif
		exit(EXIT_SUCCESS);
	} else {
		/* child -- becoming a group leader */
		#ifdef DEBUG
			printf(_("child process #1 detaching\n"));
		#endif
		setsid();
		pid = fork();
		if (pid) {
			/* parent -- just exit */
			#ifdef DEBUG
				printf(_("Parent process #2 exiting\n"));
			#endif
			exit(EXIT_SUCCESS);
		} else {
			/* child will never be able to regain a controlling terminal */
			#ifdef DEBUG
				printf(_("child process #2 detaching\n"));
			#endif
			/* goal: permissions of 666 & ~022 = 644 for the created files */
			umask(022);
			/* redirection for standards I/O */
			close(0);
			if(open("/dev/null",O_RDONLY)==-1) {
				error_log(_("daemonize: stdin redirection failed"));
				exit(EXIT_FAILURE);
			}
			close(1);
			if(open("/dev/null",O_WRONLY)==-1) {
				error_log(_("daemonize: stdout redirection failed"));
				exit(EXIT_FAILURE);
			}	
			close(2);
			if(open("/dev/null",O_WRONLY)==-1) {
				error_log(_("daemonize: stderr redirection failed"));
				exit(EXIT_FAILURE);
			}
		}	
	}
}

int change_environement(struct configuration_struct settings) {
/* changing directory to log_file_path if necessary */
/* it also changes the UID if requested to do so */
/* returns EXIT_SUCCESS or EXIT_FAILURE */

	if(settings.file_log==EXIT_SUCCESS) {
		if(chdir(settings.log_file_path)!=EXIT_SUCCESS) {
			fprintf(stderr,_("change_environement: cd to %s failed\n"),settings.log_file_path);
			if(settings.syslog==EXIT_SUCCESS) {
				syslog(LOG_ERR,_("change_environement: cd to %s failed\n"),settings.log_file_path);
				syslog(LOG_ERR,_("Halting %s"),GM4LIN_NAME);
				closelog();
			}
			return EXIT_FAILURE;
		}
		if(settings.syslog==EXIT_SUCCESS) {
			syslog(LOG_ERR,_("Successfully changed directory to %s\n"),settings.log_file_path);
		}
	}
	/* 0 is uid for root, so there is nothing to do if "0" is requested: it is either already done or prohibited ! */
	if(settings.uid!=0) {
		if(setuid(settings.uid)!=EXIT_SUCCESS) error_log(_("change_environement: can not set requested User ID"));
	}
	return EXIT_SUCCESS;
}
